/*                          UX-Framework                               
 *                                                                 
 *  iZE Co.,Ltd. Copyright 2009 All rights reserved.          
 *  This file is distributed under the terms of the GNU Lesser 
 *  General Public License, described in file LICENSE.                                     
 */
package jp.ize.ux.acts;

// {{{ imports
import jp.ize.ux.UXObject;
import jp.ize.ux.acts.Act;
import jp.ize.ux.geom.UXPoint;
import jp.ize.ux.utils.Util;
import jp.ize.ux.tween.UXTween;
// }}}
// {{{ typedef LayoutState
/**
 * LayoutActが必要な情報です。
 */
typedef LayoutState = {
	> BasicStateType,
	/** レイアウト対象オブジェクト */
	var items(default,default) : Dynamic;
}
// }}}
// {{{ typedef LayoutType1Parameter =
/**
 * タイプ1レイアウトパラメーターです。
 */
typedef LayoutType1Parameter =
{
	> ActParameter,
	// {{{ var points : Array<UXPoint>;
	/**
	 * 座標の配列です。
	 */
	var points : Array<UXPoint>;
	// }}}
}
// }}}
// {{{ typedef LayoutType2Parameter =
/**
 * タイプ2レイアウトパラメーターです。
 */
typedef LayoutType2Parameter =
{
	> ActParameter,
	// {{{ var names : Array<String>;
	/**
	 * キーになる名前の配列です。
	 */
	var names : Array<String>;
	// }}}
	// {{{ var points : Hash<UXPoint>;
	/**
	 * ハッシュ形式の座標です。
	 */
	var points : Hash<UXPoint>;
	// }}}
}
// }}}
// {{{ class LayoutAct extends Act
/**
 * LayoutActクラス<br>
 * 直線上の動きを表現するクラスです。<br>
 *
 * @author		iZE Co., Ltd.<br>
 * @version		$Id$<br>
 */
class LayoutAct extends Act
{
	// {{{ public function new()
	/**
	 * コンストラクタ。
	 */
	public function new()
	{
		super();
	}
	// }}}
	// {{{ public function layout1( ?lp:LayoutType1Parameter, ?interp:LayoutState->LayoutType1Parameter ) : LayoutState -> Void
	/**
	 * 配列で持っているオブジェクトをレイアウトするアクションです。
	 */
	public function layout1( ?lp:LayoutType1Parameter, ?interp:LayoutState->LayoutType1Parameter ) : LayoutState -> Void
	{
		var me = this;
		return function( state : LayoutState ) : Void {
			me.initSync(state.items.length);
			me.setSyncDoneHandler( function(){
				if ( state.subject!=null ) {
					state.subject.notify(Act.STOP);
				}
			});
			var param = lp;
			if ( interp!=null ) param = interp(state);
			for (i in 0...state.items.length) {
				var c = state.items[i];
				var getter = function(obj:UXObject): {x:Float,y:Float} {
					return {x:obj.x,y:obj.y};
				};
				var setter = function(obj:UXObject, init:{x:Float,y:Float}, end:{x:Float,y:Float}, v:Float) {
					obj.x = init.x+(end.x-init.x)*v;
					obj.y = init.y+(end.y-init.y)*v;
				};
				var end = {x:param.points[i].x,y:param.points[i].y};
				var tw = new UXTween<UXObject,{x:Float,y:Float}>(c, end, getter, setter, param.time,
							param.transition);
				tw.setEndTweenHandler( function(e:Dynamic){
					me.doneSync(i);
				});
				var id = "layout1" + Std.string(i);
				if ( !me.tm.objects.exists(id) ) {
					me.tm.registObject(id,state);
				}
				me.tm.addTweenChain(id,tw); 
				me.tm.start(id,false,state.target);
			}
		};
	}
	// }}}
	// {{{ public function layout2( ?lp:LayoutType2Parameter, ?interp:LayoutState->LayoutType2Parameter ) : LayoutState -> Void
	/**
	 * 配列で持っているオブジェクトをレイアウトするアクションです。
	 */
	public function layout2( ?lp:LayoutType2Parameter, ?interp:LayoutState->LayoutType2Parameter ) : LayoutState -> Void
	{
		var me = this;
		return function( state : LayoutState ) : Void {
			var param = lp;
			if ( interp!=null ) param = interp(state);
			me.initSync(param.names.length);
			me.setSyncDoneHandler( function(){
				if ( state.subject!=null ) {
					state.subject.notify(Act.STOP);
				}
			});
			for (i in 0...param.names.length) {
				var name = param.names[i];
				var c = state.items.get(name);
				var getter = function(obj:UXObject): {x:Float,y:Float} {
					return {x:obj.x,y:obj.y};
				};
				var setter = function(obj:UXObject, init:{x:Float,y:Float}, end:{x:Float,y:Float}, v:Float) {
					obj.x = init.x+(end.x-init.x)*v;
					obj.y = init.y+(end.y-init.y)*v;
				};
				var end = {x:param.points.get(name).x,y:param.points.get(name).y};
				var tw = new UXTween<UXObject,{x:Float,y:Float}>(c, end, getter, setter, param.time,
							param.transition);
				tw.setEndTweenHandler( function(e:Dynamic){
					me.doneSync(i);
				});
				var id = "layout2" + Std.string(i);
				if ( !me.tm.objects.exists(id) ) {
					me.tm.registObject(id,state);
				}
				me.tm.addTweenChain(id,tw); 
				me.tm.start(id,false,state.target);
			}
		};
	}
	// }}}
}
// }}}
